#ifndef _DATA_STRUCT_H_
#define _DATA_STRUCT_H_
#include "flv_main.h"
#include <unordered_map>
#include "user.h"
#include "stream_entry.h"
#define  ID2INDEX(_x)       (_x/32)
#define  ID2BIT(_x)         (_x%32)
#define  MASK(_x)           (oal_uint32)(1<<(ID2BIT(_x)))  
#define  BIT_MASK(_x)       (oal_uint32)(1<<(_x))
#define  LOCAL2ID(_x,_y)    ((32*_x)+_y)  

enum category
{
    USER,
    PUSHER,
    BUTTT
};
typedef struct bitmap
{
    oal_int32  bits_len;//位图能展示的总长度
    oal_uint32  *bits_flag;//位图数组
    oal_int32  max_num;//最大描述符
    oal_int32  max_avail_num;//最大可用描述符
}Bitmap;
typedef struct map_item
{
    category    type;    
    oal_uint32  id;
}Item;
class data_struct
{
    public:
    oal_bool            is_init;
    Buffer              push_socket_buffer;//推流socketid队列
    queue<oal_int32>   *entry_sched_queue;//实体调度队列
    pthread_mutex_t     esq_mutex;//用于实体调度队列的互斥锁
	pthread_cond_t      esq_cond; //用于实体调度的条件变量
    stream_entry       *entry_head;//flv实体队列
    pthread_spinlock_t  entry_head_lock;//flv实体队列锁
    Bitmap              stream_entry_set;//实体队列的位图
    user               *user_head;//拉流用户队列
    pthread_spinlock_t  user_head_lock;//拉流用户队列锁
    Bitmap              user_set;//拉流用户队列位图   
    unordered_map<oal_uint32,oal_uint32>    *fd2entry_map; //进程实体文件描述符与实际flv实体 id的映射  
    unordered_map<oal_uint32,oal_uint32>    *fd2user_map; //进程实体文件描述符与拉流用户实体 id的映射  
    unordered_map<oal_uint32,oal_uint32>    *pusher2enrtry_map;//推流用户和实体id的映射
    data_struct()
    {
        is_init = false;
        pthread_spin_init(&user_head_lock,PTHREAD_PROCESS_PRIVATE);
        pthread_spin_init(&entry_head_lock,PTHREAD_PROCESS_PRIVATE);
        pthread_mutex_init(&esq_mutex, NULL);
	    pthread_cond_init(&esq_cond, NULL);
        entry_sched_queue   = new queue<oal_int32>();
        fd2entry_map        = new unordered_map<oal_uint32,oal_uint32>();
        fd2user_map         = new unordered_map<oal_uint32,oal_uint32>();
        pusher2enrtry_map   = new unordered_map<oal_uint32,oal_uint32>();
        
    }
    ~ data_struct()
    {
        delete entry_sched_queue;
        delete fd2entry_map;
        delete pusher2enrtry_map;
        delete fd2user_map;
        if(is_init)
        {
            buffer_delete(&push_socket_buffer);
            delete[] entry_head;
            free( stream_entry_set.bits_flag);
            delete[] user_head;
            free(user_set.bits_flag);
        }
        
    }
    /*
    psb_len : 推流队列长度
    eh_len ：flv实体队列实体队列长度
    uh_len ：拉流用户队列长度
    */
    oal_int8 init(oal_uint32 psb_len ,oal_uint32  eh_len ,oal_uint32 uh_len)
    {
        if(buffer_init(&push_socket_buffer,sizeof(oal_uint32),psb_len) < 0)
        {
            printf("push_socket_buffer init failed\n");
            return -1;
        }
        entry_head = new stream_entry[eh_len];
        if(entry_head == oal_ptr_null)
        {
            printf("entry_head malloc failed\n");
            return -1;
        }
        stream_entry_set.bits_len = eh_len;
        stream_entry_set.max_num  = 0;
        stream_entry_set.max_avail_num  = 0;
        stream_entry_set.bits_flag = (oal_uint32 *)malloc((eh_len + 31)/32);
        if(stream_entry_set.bits_flag == oal_ptr_null)
        {
            printf("stream_entry_set.bits_flag malloc failed\n");
            return -1;
        }
        user_head = new user[uh_len];
        if(user_head == oal_ptr_null)
        {
            printf("user_head malloc failed\n");
            return -1;
        }
        user_set.bits_len       = uh_len;
        user_set.max_num        = 0;
        user_set.max_avail_num  = 0;
        user_set.bits_flag      = (oal_uint32 *)malloc((uh_len + 31)/32);
        if(user_set.bits_flag == oal_ptr_null)
        {
            printf("user_set.bits_flag malloc failed\n");
            return -1;
        }
        return 0;
        is_init = true;
    }
    oal_int32 findnext_avail(oal_uint32 next_id , oal_uint32 *root)
    {
        while(next_id++ <= user_set.max_num)
        {
            if(root[ID2INDEX(next_id)]&MASK(next_id) == 0)
            {
                return next_id;
            }
        }
        return next_id;
    }
    oal_int32 get_user_id()
    {
        oal_int32  new_id;
        oal_int32  next_id;
        oal_int32  distance;
        pthread_spin_lock(&user_head_lock); //应该用互斥锁
        if(user_set.max_avail_num >= user_set.bits_len)
        {
            pthread_spin_unlock(&user_head_lock);
            return -1;
        }
        new_id          = user_set.max_avail_num + 1;
        user_set.bits_flag[ID2INDEX(new_id)] |= MASK(new_id);
        next_id         = user_set.max_avail_num + 2;
        next_id = findnext_avail((oal_uint32)next_id,user_set.bits_flag) - 1;
        user_set.max_avail_num = next_id;
        if(next_id > user_set.max_num)
        {
            next_id = user_set.max_num;
        }
        pthread_spin_unlock(&user_head_lock);
        return new_id;
    }
    oal_void free_user_id(oal_int32 user_id)
    {
        pthread_spin_lock(&user_head_lock); //应该用互斥锁
        user_set.bits_flag[ID2INDEX(user_id)] &= (~MASK(user_id));
        if(user_id <= user_set.max_avail_num)
        {
            user_set.max_num = user_id - 1;
        }
        if(user_set.max_num == user_id)
        {
            user_set.max_num = user_id - 1;
        }
        pthread_spin_unlock(&user_head_lock);
        return ;
    }

    oal_int32 get_stream_id()
    {
        oal_int32  new_id;
        oal_int32  next_id;
        pthread_spin_lock(&entry_head_lock); //应该用互斥锁
        if(stream_entry_set.max_avail_num >= stream_entry_set.bits_len)
        {
            pthread_spin_unlock(&entry_head_lock);
            return -1;
        }
        new_id          = stream_entry_set.max_avail_num + 1;
        stream_entry_set.bits_flag[ID2INDEX(new_id)] |= MASK(new_id);
        next_id         = stream_entry_set.max_avail_num + 2;
        next_id = findnext_avail((oal_uint32)next_id,stream_entry_set.bits_flag) - 1;
        stream_entry_set.max_avail_num = next_id;
        if(next_id > stream_entry_set.max_num)
        {
            next_id = stream_entry_set.max_num;
        }
        pthread_spin_unlock(&entry_head_lock);
        return new_id;
    }
    oal_void free_stream_id(oal_int32 user_id)
    {
        pthread_spin_lock(&entry_head_lock); //应该用互斥锁
        stream_entry_set.bits_flag[ID2INDEX(user_id)] &= (~MASK(user_id));
        if(user_id <= stream_entry_set.max_avail_num)
        {
            stream_entry_set.max_num = user_id - 1;
        }
        if(stream_entry_set.max_num == user_id)
        {
            stream_entry_set.max_num = user_id - 1;
        }
        pthread_spin_unlock(&entry_head_lock);
        return ;
    }
    oal_int32 get_sched_entry()
    {
        oal_int32 real_fd;
        pthread_mutex_lock(&esq_mutex);
		while (entry_sched_queue->empty())
		{
			pthread_cond_wait(&esq_cond, &esq_mutex);//无条件变量时，别的线程释放了锁则不管资源可不可用，此线程都会去执行后续逻辑，而用了条件变量之后，则此线程会等到资源可用时才会执行后续逻辑，减小cpu消耗
		}
        real_fd = entry_sched_queue->front();
        entry_sched_queue->pop();
        pthread_mutex_unlock(&esq_mutex);
        return real_fd;
    }
    oal_int8 put_sched_entry(oal_int32 fd)
    {
        pthread_mutex_lock(&esq_mutex);
	    entry_sched_queue->push(fd);
	    pthread_cond_signal(&esq_cond);
        pthread_mutex_unlock(&esq_mutex);
        return 0;
    }
    oal_void insert_entrymap(oal_uint32 sock_fd,oal_uint32 entry_fd )
    {
        //加锁
        fd2entry_map->insert(pair<oal_uint32,oal_uint32>(sock_fd,entry_fd));
        printf("fd2entry_map->insert socket id[%d] real_id [%d]\n",sock_fd,entry_fd);
    }
    oal_void delete_entrymap(oal_uint32 sockfd)
    {
        //枷锁
        fd2entry_map->erase(sockfd);
    }
};
#endif